package cmd

import (
	"errors"
	"fmt"
	"io/fs"
	"os"
	"os/exec"
	"path/filepath"
	"sort"
	"strconv"
	"strings"

	"github.com/spf13/cobra"
)

// istip 判断是默认tip还是指定版本
func istip(args []string) string {
	var typ string
	if len(args) == 0 {
		typ = "tip"
	} else {
		typ = args[0]
	}
	return typ
}

// Exec 执行命令
func Exec(cmdroot *cobra.Command, commind ...string) error {
	cmd := exec.Command(commind[0], commind[1:]...)
	buf, err := cmd.CombinedOutput()
	cmdroot.Println(string(buf))
	return err
}

// checkVersion 检查版本号是否正确
func checkVersion(typ string) error {
	if typ == "tip" {
		return nil
	}
	//Note:后面肯定不是 typ=="tip"
	if !strings.HasPrefix(typ, "v") { //检查版本号是否正确
		return errors.New("版本号应该以v开头")
	}
	vernum := strings.Split(typ, ".")
	if len(vernum) != 3 {
		return errors.New("版本号应该是vx.y.z")
	}
	//检查是否是不能处理的版本，对于版本号vx.y.z y大于4或 y等于4同时z大于1才是可以处理的
	ok, err := cmpStrNum(vernum[1], "4")
	if !ok || err != nil {
		return errors.New("只能处理大于等于v0.4.0的版本")
	}
	return nil
}

// MinorVersionNumberAndRevisedVersionNumber 获取次要版本号和补丁版本号
func MinorVersionNumberAndRevisedVersionNumber(s string) (int, int, error) {
	vernum := strings.Split(s, ".")
	if len(vernum) != 3 {
		return 0, 0, errors.New("版本号应该是vx.y.z")
	}
	n1, err := strconv.Atoi(vernum[1])
	if err != nil {
		return 0, 0, err
	}
	n2, err := strconv.Atoi(vernum[2])
	if err != nil {
		return 0, 0, err
	}
	return n1, n2, nil
}

func cmpStrNum(str1, str2 string) (bool, error) {
	n1, err := strconv.Atoi(str1)
	if err != nil {
		return false, err
	}
	n2, err := strconv.Atoi(str2)
	if err != nil {
		return false, err
	}
	return n1 > n2, nil
}

// GetComplierDirInfo 从root获取所有的编译器目录信息
func GetComplierDirInfo(root string) SortComplierDirInfo {
	var ret = make([]ComplierDirInfo, 0)
	filepath.WalkDir(root, func(path string, d fs.DirEntry, err error) error { //遍历目录树
		if err != nil {
			return err
		}
		_, file := filepath.Split(path)
		if !strings.HasPrefix(file, "u@") { //如果不是某个版本的编译器根目录，判断标准为前缀不是
			return nil
		}
		ret = append(ret, ComplierDirInfo{Path: path, Version: file})
		return nil
	})
	sort.Sort(SortComplierDirInfo(ret))
	return ret
}

// IsVersion 判断 $U_HOME\sdk是否安装了指定版本编译器
// 假定传入的版本号正确
func IsVersion(typ string) bool {
	info := GetComplierDirInfo(u_env_var.U_Complier_Sdk)
	return info.Find(typ).Version != ""
}

// Link 将 $U_HOME\sdk\link 设置为指定编译器版本的目录符号链接
func Link(typ string) error {
	err := os.Remove(u_env_var.U_Complier_Link)
	if err != nil {
		return fmt.Errorf("修改 %s 链接的目录地址失败 错误信息：%w", u_env_var.U_Complier_Link, err)
	}
	err = os.Symlink(filepath.Join(u_env_var.U_Complier_Sdk, `u@`+typ), u_env_var.U_Complier_Link)
	if err != nil {
		return fmt.Errorf("修改 %s 链接的目录地址失败 错误信息：%w", u_env_var.U_Complier_Link, err)
	}
	return nil
}
